% ALGORITHM
% 
% - do a first coarse segmentation dividing into sets of raw data events
%   that are separated by 1 minute of 'no raw data events'
%
% - take each of these 'super-occupancy-events' and perform a merge of the
%   'door open - close - open / close - open - close' tripletes that are
%   'too fast', i.e., that happen because of the noisiness of the door open
%   sensor
%
% - 
%
function 	[	aiTimesOfBeginningsOfOccupancyEvents,			...
				aiTimesOfEndingsOfOccupancyEvents		]	=	...
					SegmentOccupancyEvents(						...
						aafRawData								)
	%
	%
	global tFileID;
	global bPrintDebugInformation;
	%
	if( numel( aafRawData ) == 0 )
		%
		aiTimesOfBeginningsOfOccupancyEvents	= [];
		aiTimesOfEndingsOfOccupancyEvents		= [];
		%
		if( bPrintDebugInformation )
			%
			fprintf(tFileID, 'All the raw data have been removed, segmentin noting.\n');
			%
		end;%
		%
		return;
		%
	end;%
	%
	% DEBUG
	if( bPrintDebugInformation )
		%
		fprintf(tFileID, 'Segmenting the events\n');
		%
	end;%
	%	
	tParameters = PeopleCounters.LoadParameters();
	%
	% ---------------------------------------------------------------------
	% compute the time interval between two row data events
	afTimeIntervals = diff( aafRawData(:,2) );
	aiIndexesOfBigTimeIntervals = find(afTimeIntervals > tParameters.iThresholdForSuperEventsSegmentation);
	%
	% find the division of the superevents
	aiIndexesOfBeginningsOfSuperEvents	= [ 1 ; aiIndexesOfBigTimeIntervals + 1 ];
	aiIndexesOfEndingsOfSuperEvents		= [ aiIndexesOfBigTimeIntervals ; numel(aafRawData( :, 2 )) ];
	%
	% allocate the storage for the occupancy events
	aiTimesOfBeginningsOfOccupancyEvents	= [];
	aiTimesOfEndingsOfOccupancyEvents		= [];
	%
	%
	% DEBUG
	if( bPrintDebugInformation )
		%
		fprintf(tFileID,																						...
				'Segmenting into super-events: found %d super-events spanning a total of %d raw-data events\n',	...
				numel(aiIndexesOfBeginningsOfSuperEvents),	...
				numel(aafRawData(:, 1))						);
		%
	end;%
	%
	% DEBUG
% 	[	(1:numel(aafRawData(:, 2)))', aafRawData(:, 2), [afTimeIntervals ; 0]	]
% 	[	aiIndexesOfBeginningsOfSuperEvents, aiIndexesOfEndingsOfSuperEvents		]
% 	pause
	%
	%
	% ---------------------------------------------------------------------
	% do the merging of the open/close/open, close/open/close tripletes
	for iSuperEvent = 1:numel( aiIndexesOfBeginningsOfSuperEvents )
		%
		% for readability
		aafCurrentSuperEvent =													...
			aafRawData(	aiIndexesOfBeginningsOfSuperEvents(iSuperEvent):		...
						aiIndexesOfEndingsOfSuperEvents(iSuperEvent),		:	);
		%		
		% find the transitions open->close
		[	aaiDoorTransitions,					...
	   		aaiLaser1Transitions,				...
	   		aaiLaser2Transitions	] =			...
	   			PeopleCounters.FindOpeningClosingTransitions( aafCurrentSuperEvent );
		%
		% merge also the 'too near' dooropen->doorclose transitions. These will correspond
		% to single occupancy events
		aaiDoorTransitions = 												...
			PeopleCounters.MergeTooCloseTransitions( aaiDoorTransitions,			...
												tParameters.iThresholdForDoorEventsMerging	);
		%
		% ---------------------------------------------------------------------
		% assign to each door opening transition the various laser transitions
		iNumberOfDoorEvents = numel( aaiDoorTransitions ) / 2; % remember that this is a matrix N times 2
		%
		% DEBUG
		if( bPrintDebugInformation )
			%
			fprintf(tFileID, '\n\n\n-----------------------------------\nSegmenting super-event %d into single occupancy events: found %d door events\n', iSuperEvent, iNumberOfDoorEvents);
			%
		end;%
		%		
		if( iNumberOfDoorEvents > 0 )
			%
			[	aiLaser1TransitionsEventsLabels,							...
				aiLaser2TransitionsEventsLabels	] =							...
					PeopleCounters.AssociateLaserTransitionsToDoorTransitions(	...
						aaiDoorTransitions,									...
						aaiLaser1Transitions,								...
						aaiLaser2Transitions								);
			%
			% for each event, check what is assigned to that event, and find
			% the minimum and the maximum times
			for iDoorEvent = 1:iNumberOfDoorEvents;
				%
				aiTimesOfBeginningsOfOccupancyEvents(end+1) =												...
						min( [	aaiLaser1Transitions( aiLaser1TransitionsEventsLabels == iDoorEvent, 1) ;	...
								aaiLaser2Transitions( aiLaser2TransitionsEventsLabels == iDoorEvent, 1) ;	...
								aaiDoorTransitions(iDoorEvent, 1)										]	);
				%
				aiTimesOfEndingsOfOccupancyEvents(end+1) =													...
						max( [	aaiLaser1Transitions( aiLaser1TransitionsEventsLabels == iDoorEvent, 2) ;	...
								aaiLaser2Transitions( aiLaser2TransitionsEventsLabels == iDoorEvent, 2) ;	...
								aaiDoorTransitions(iDoorEvent, 2)										]	);
				%
				% DEBUG
				if( bPrintDebugInformation )
					%
					fprintf(tFileID, 'Occupancy event %d: starts at %d and ends at %d\n',	...
							numel(aiTimesOfBeginningsOfOccupancyEvents),			...
							aiTimesOfBeginningsOfOccupancyEvents(end),				...
							aiTimesOfEndingsOfOccupancyEvents(end)					);				
					%
				end;%
				%
			end;% cycle on the single occupancy events
			%
		end;% if there exists at least one occupancy event
		%
	end;% cycle on the super events
	%
	%
	% DEBUG
	if( bPrintDebugInformation )
		%
		fprintf(tFileID, 'Ended segmenting the events\n');
		%
	end;%
	%	
end % function

